use crate::config::get_load_global_config;
use crate::r#struct::{Candlestick, OrderResult, SymbolOrderData};
use binance_spot_connector_rust::{
    http::Credentials,
    hyper::{BinanceHttpClient, Error},
    market::{self, klines::KlineInterval},
    trade,
    trade::order::Side,
};
use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, Utc};
use mysql::prelude::*;
use mysql::*;
use rust_decimal::prelude::FromPrimitive;
use rust_decimal::Decimal;
use serde::de::StdError;
use std::fmt;
use std::time::Duration;
use tokio::time::sleep;
// 策略主逻辑
pub(crate) struct VegasTunnelStrategy {
    symbol: String,
    start_date: NaiveDate,
    end_date: NaiveDate,
}
impl VegasTunnelStrategy {
    pub(crate) fn new(
        symbol: &str,
        start: NaiveDate,
        end: NaiveDate,
    ) -> Result<Self, Box<dyn std::error::Error>> {
        Ok(Self {
            symbol: symbol.to_string(),
            start_date: start,
            end_date: end,
        })
    }

    pub async fn run(&self) -> Result<(), Box<dyn std::error::Error>> {
        let local_start: DateTime<Local> = Local::now();
        println!(
            "========================Binance Vegas通道策略-执行开始时间:{} ========================",
            local_start.format("%Y-%m-%d %H:%M:%S")
        );
        // 获取最新 1000 根K线
        let candlesticks = get_candlesticks(&self.symbol, 1000).await?;
        let closes: Vec<f64> = candlesticks
            .iter()
            .map(|b| b.close.to_string().parse::<f64>().unwrap())
            .collect();
        let highs: Vec<f64> = candlesticks
            .iter()
            .map(|b| b.high.to_string().parse::<f64>().unwrap())
            .collect();
        let lows: Vec<f64> = candlesticks
            .iter()
            .map(|b| b.low.to_string().parse::<f64>().unwrap())
            .collect();
        let timestamps: Vec<DateTime<Utc>> = candlesticks
            .iter()
            .map(|b| {
                let ts = b.close_time; // u64，毫秒级时间戳
                let secs = (ts / 1000) as i64; // 提取秒数
                let nsecs = ((ts % 1000) * 1_000_000) as u32; // 提取毫秒并转为纳秒
                DateTime::from_timestamp(secs, nsecs).expect("Invalid timestamp")
            })
            .collect();

        // 计算技术指标
        let sm2 = ema(&closes, 12);
        let sm6 = sma(&closes, 240);
        let (_, bb_upper, bb_lower) = bollinger_bands(&closes, 20, 2.0);
        let macd = macd(&closes, 48, 56);
        let f1 = ema(&closes, 36);
        let f2 = ema(&closes, 43);
        let f3 = ema(&closes, 144);
        let f4 = ema(&closes, 169);
        let f5 = ema(&closes, 576);
        let f6 = ema(&closes, 676);

        // 检查当前时间是否在范围内
        let current_timestamp = timestamps.last().ok_or("No timestamps available")?;
        let start_time = self
            .start_date
            .and_hms_opt(0, 0, 0)
            .ok_or("Invalid start date")?
            .and_utc();
        let end_time = self
            .end_date
            .and_hms_opt(0, 0, 0)
            .ok_or("Invalid end date")?
            .and_utc();

        let in_range = current_timestamp >= &start_time && current_timestamp < &end_time;
        if !in_range {
            println!("Current timestamp out of date range");
            return Ok(());
        }

        // 在使用技术指标时添加检查
        if macd.is_empty()
            || f1.is_empty()
            || f3.is_empty()
            || f4.is_empty()
            || f5.is_empty()
            || f6.is_empty()
            || bb_upper.is_empty()
            || bb_lower.is_empty()
        {
            println!("Not enough data for technical indicators");
            return Ok(());
        }

        // 交易逻辑（只基于最后两根K线）
        let unit = 0.01;
        let each_call_position = 1.0 * unit;
        let each_put_position = 1.0 * unit;

        // 获取最新的技术指标值
        let latest_macd = macd.get(macd.len() - 2).ok_or("No MACD data available")?;
        let latest_f1 = f1.get(f1.len() - 2).ok_or("No F1 data available")?;
        let latest_f3 = f3.get(f3.len() - 2).ok_or("No F3 data available")?;
        let latest_f4 = f4.get(f4.len() - 2).ok_or("No F4 data available")?;
        let latest_f5 = f5.get(f5.len() - 2).ok_or("No F5 data available")?;
        let latest_f6 = f6.get(f6.len() - 2).ok_or("No F6 data available")?;
        let latest_bb_upper = bb_upper
            .get(bb_upper.len() - 2)
            .ok_or("No Bollinger Bands data available")?;
        let latest_bb_lower = bb_lower
            .get(bb_lower.len() - 2)
            .ok_or("No Bollinger Bands data available")?;
        // 调试代码时候打开，辅助打印。
        println!("Last MACD: {:?}", latest_macd);
        println!("Last F1-【36】: {:?}", latest_f1);
        println!("Last F3-【144】: {:?}", latest_f3);
        println!("Last F4-【169】: {:?}", latest_f4);
        println!("Last F5-【576】: {:?}", latest_f5);
        println!("Last F6-【676】: {:?}", latest_f6);
        println!("Last Bollinger Bands Upper: {:?}", latest_bb_upper);
        println!("Last Bollinger Bands Lower: {:?}", latest_bb_lower);
        // 波段多 (buy2)
        let entry_id_2 = "buy2波段多";
        if crossunder(&f3, &f1) && *latest_macd > 0.0 {
            println!("===============开仓【波段多】-buy2===============");
            let order_result =
                place_order(self.symbol.clone(), Side::Buy, each_call_position).await?;
            let query_result = query_from_db(entry_id_2, &self.symbol)?;
            let db_net_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            save_to_db(
                self.symbol.clone(),
                entry_id_2.to_string(),
                order_result.price.parse().unwrap(),
                "Market".to_string(),
                "Buy".to_string(),
                each_call_position,
                db_net_position + each_call_position,
                order_result.order_id.to_string(),
                order_result.order_status,
            )?;
        }
        if crossunder(&f3, &f5) {
            let query_result = query_from_db(entry_id_2, &self.symbol)?;
            let sell_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            println!("===============【关波段多】-close操作===============");
            if sell_position > 0.0 {
                let order_result =
                    close_position(self.symbol.clone(), Side::Sell, sell_position).await?;
                save_to_db(
                    self.symbol.clone(),
                    entry_id_2.to_string(),
                    order_result.price.parse().unwrap(),
                    "Market".to_string(),
                    "Sell".to_string(),
                    sell_position,
                    0.0,
                    order_result.order_id.to_string(),
                    order_result.order_status,
                )?;
            } else {
                println!("===============仓位为0.0，跳过【关波段多】-close操作===============");
            }
        }

        // 多策略1 (buy1)
        let entry_id_1 = "buy1买中期";
        if crossover(&lows, &f3) && *latest_macd > 0.0 && *latest_f3 > *latest_f6 {
            println!("===============开仓【买中期】-buy1===============");
            let order_result =
                place_order(self.symbol.clone(), Side::Buy, each_call_position).await?;
            let query_result = query_from_db(entry_id_1, &self.symbol)?;
            let db_net_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            save_to_db(
                self.symbol.clone(),
                entry_id_1.to_string(),
                order_result.price.parse().unwrap(),
                "Market".to_string(),
                "Buy".to_string(),
                each_call_position,
                db_net_position + each_call_position,
                order_result.order_id.to_string(),
                order_result.order_status,
            )?;
        }
        if *latest_macd < 0.0 || *latest_f3 < *latest_f6 || crossunder_upper(&closes, &bb_upper) {
            let query_result = query_from_db(entry_id_1, &self.symbol)?;
            let sell_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            println!("===============【关中期】-close操作===============");
            if sell_position > 0.0 {
                let order_result =
                    close_position(self.symbol.clone(), Side::Sell, sell_position).await?;
                save_to_db(
                    self.symbol.clone(),
                    entry_id_1.to_string(),
                    order_result.price.parse().unwrap(),
                    "Market".to_string(),
                    "Sell".to_string(),
                    sell_position,
                    0.0,
                    order_result.order_id.to_string(),
                    order_result.order_status,
                )?;
            } else {
                println!("===============仓位为0.0，跳过【关中期】-close操作===============");
            }
        }

        // 多策略3 (buy3)
        let entry_id_3 = "buy3买短期";
        if *latest_macd > 0.0 && crossunder(&lows, &f1) && *latest_f1 > *latest_f4 {
            println!("===============开仓【买短期】-buy3===============");
            let order_result =
                place_order(self.symbol.clone(), Side::Buy, each_call_position).await?;
            let query_result = query_from_db(entry_id_3, &self.symbol)?;
            let db_net_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            save_to_db(
                self.symbol.clone(),
                entry_id_3.to_string(),
                order_result.price.parse().unwrap(),
                "Market".to_string(),
                "Buy".to_string(),
                each_call_position,
                db_net_position + each_call_position,
                order_result.order_id.to_string(),
                order_result.order_status,
            )?;
        }
        // 平仓
        // println!(
        //     "crossunder_upper(&closes, &bb_upper):{}",
        //     crossunder_upper(&closes, &bb_upper,0.999)
        // );
        if *latest_macd < 0.0 || *latest_f1 < *latest_f4 || crossunder_upper(&closes, &bb_upper) {
            let query_result = query_from_db(entry_id_3, &self.symbol)?;
            let sell_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            println!("===============【关短期】-close操作===============");
            if sell_position > 0.0 {
                let order_result =
                    close_position(self.symbol.clone(), Side::Sell, sell_position).await?;
                save_to_db(
                    self.symbol.clone(),
                    entry_id_3.to_string(),
                    order_result.price.parse().unwrap(),
                    "Market".to_string(),
                    "Sell".to_string(),
                    sell_position,
                    0.0,
                    order_result.order_id.to_string(),
                    order_result.order_status,
                )?;
            } else {
                println!("===============仓位为0.0，跳过【关短期】-close操作===============");
            }
        }

        // 多策略4 (buy4)
        let entry_id_4 = "buy4买长期";
        if *latest_macd > 0.0 && crossunder(&lows, &f5) && *latest_f4 > *latest_f5 {
            println!("===============开仓【买长期】-buy4===============");
            let order_result =
                place_order(self.symbol.clone(), Side::Buy, each_call_position).await?;
            let query_result = query_from_db(entry_id_4, &self.symbol)?;
            let db_net_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            save_to_db(
                self.symbol.clone(),
                entry_id_4.to_string(),
                order_result.price.parse().unwrap(),
                "Market".to_string(),
                "Buy".to_string(),
                each_call_position,
                db_net_position + each_call_position,
                order_result.order_id.to_string(),
                order_result.order_status,
            )?;
        }
        // 平仓
        if *latest_macd < 0.0 || *latest_f4 < *latest_f6 || crossunder_upper(&closes, &bb_upper) {
            let query_result = query_from_db(entry_id_4, &self.symbol)?;
            let sell_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            println!("===============【关长期】-close操作===============");
            if sell_position > 0.0 {
                let order_result =
                    close_position(self.symbol.clone(), Side::Sell, sell_position).await?;
                save_to_db(
                    self.symbol.clone(),
                    entry_id_4.to_string(),
                    order_result.price.parse().unwrap(),
                    "Market".to_string(),
                    "Sell".to_string(),
                    sell_position,
                    0.0,
                    order_result.order_id.to_string(),
                    order_result.order_status,
                )?;
            } else {
                println!("===============仓位为0.0，跳过【关长期】-close操作===============");
            }
        }

        // 空策略1 (sell1)
        let entry_id_5 = "sell1空短期";
        if *latest_macd < 0.0
            && crossunder(&highs, &f1)
            && *latest_f1 < *latest_f3
            && *latest_f3 < *latest_f6
        {
            println!("===============开仓【空短期】-sell1===============");
            let order_result =
                place_order(self.symbol.clone(), Side::Sell, each_put_position).await?;
            let query_result = query_from_db(entry_id_5, &self.symbol)?;
            let db_net_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            save_to_db(
                self.symbol.clone(),
                entry_id_5.to_string(),
                order_result.price.parse().unwrap(),
                "Market".to_string(),
                "Sell".to_string(),
                each_put_position,
                db_net_position + each_put_position,
                order_result.order_id.to_string(),
                order_result.order_status,
            )?;
        }
        // 平仓
        if *latest_macd > 0.0 || *latest_f1 > *latest_f4 || lower_crossunder(&bb_lower, &closes) {
            let query_result = query_from_db(entry_id_5, &self.symbol)?;
            let buy_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            println!("===============【关空短期】-close操作===============");
            if buy_position > 0.0 {
                let order_result =
                    close_position(self.symbol.clone(), Side::Buy, buy_position).await?;
                save_to_db(
                    self.symbol.clone(),
                    entry_id_5.to_string(),
                    order_result.price.parse().unwrap(),
                    "Market".to_string(),
                    "Buy".to_string(),
                    buy_position,
                    0.0,
                    order_result.order_id.to_string(),
                    order_result.order_status,
                )?;
            } else {
                println!("===============仓位为0.0，跳过【关空短期】-close操作===============");
            }
        }

        // 空策略2 (sell2)
        let entry_id_6 = "sell2空中期";
        if *latest_macd < 0.0 && crossunder(&highs, &f4) && *latest_f4 < *latest_f6 {
            println!("===============开仓【空中期】-sell2===============");
            let order_result =
                place_order(self.symbol.clone(), Side::Sell, each_put_position).await?;
            let query_result = query_from_db(entry_id_6, &self.symbol)?;
            let db_net_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            save_to_db(
                self.symbol.clone(),
                entry_id_6.to_string(),
                order_result.price.parse().unwrap(),
                "Market".to_string(),
                "Sell".to_string(),
                each_put_position,
                db_net_position + each_put_position,
                order_result.order_id.to_string(),
                order_result.order_status,
            )?;
        }
        // 平仓
        if *latest_macd > 0.0 || *latest_f4 > *latest_f6 || lower_crossunder(&bb_lower, &closes) {
            let query_result = query_from_db(entry_id_6, &self.symbol)?;
            let buy_position = if query_result.is_empty() {
                0.0
            } else {
                query_result[0].net_position
            };
            println!("===============【关空中期】-close操作===============");
            if buy_position > 0.0 {
                let order_result =
                    close_position(self.symbol.clone(), Side::Buy, buy_position).await?;
                save_to_db(
                    self.symbol.clone(),
                    entry_id_6.to_string(),
                    order_result.price.parse().unwrap(),
                    "Market".to_string(),
                    "Buy".to_string(),
                    buy_position,
                    0.0,
                    order_result.order_id.to_string(),
                    order_result.order_status,
                )?;
            } else {
                println!("===============仓位为0.0，跳过【关空中期】-close操作===============");
            }
        }

        let local_end: DateTime<Local> = Local::now();
        println!(
            "========================Binance Vegas通道策略-执行结束时间:{} ========================",
            local_end.format("%Y-%m-%d %H:%M:%S")
        );
        Ok(())
    }
}

// 获取K线数据（同步调用，移除多余逻辑）
async fn get_candlesticks(
    symbol: &str,
    limit: u32,
) -> Result<Vec<Candlestick>, Box<dyn std::error::Error>> {
    let max_retries = 3;
    let retry_delay = Duration::from_secs(3);
    let mut last_error = None;
    for attempt in 0..max_retries {
        match fetch_candlesticks(symbol, limit).await {
            Ok(candlesticks) => {
                // 睡眠 1 秒
                sleep(Duration::from_secs(1)).await;
                return Ok(candlesticks);
            }
            Err(e) => {
                last_error = Some(e);
                if attempt < max_retries - 1 {
                    println!(
                        "Failed to fetch candlesticks (attempt {}/{}), retrying in 3 seconds...",
                        attempt + 1,
                        max_retries
                    );
                    sleep(retry_delay).await;
                }
            }
        }
    }

    // If we've exhausted all retries, return the last error
    Err(last_error.unwrap_or_else(|| {
        Box::new(TradeError::DecimalError(
            "Failed to fetch candlesticks after three retries".to_string(),
        ))
    }))
}

// Helper function to fetch candlesticks
async fn fetch_candlesticks(
    symbol: &str,
    limit: u32,
) -> Result<Vec<Candlestick>, Box<dyn std::error::Error>> {
    let client = BinanceHttpClient::default();
    let request = market::klines(symbol, KlineInterval::Hours1).limit(limit);
    let response = client
        .send(request)
        .await
        .map_err(|e| Box::new(TradeError::from(e)) as Box<dyn StdError>)?;
    let data = response
        .into_body_str()
        .await
        .map_err(|e| Box::new(TradeError::from(e)) as Box<dyn StdError>)?;
    let klines: Vec<Vec<serde_json::Value>> = serde_json::from_str(&data)?;
    let candlesticks: Vec<Candlestick> = klines
        .into_iter()
        .map(|k| Candlestick {
            open_time: k[0].as_u64().unwrap(),
            open: k[1].as_str().unwrap().parse().unwrap(),
            high: k[2].as_str().unwrap().parse().unwrap(),
            low: k[3].as_str().unwrap().parse().unwrap(),
            close: k[4].as_str().unwrap().parse().unwrap(),
            volume: k[5].as_str().unwrap().parse().unwrap(),
            close_time: k[6].as_u64().unwrap(),
            quote_volume: k[7].as_str().unwrap().parse().unwrap(),
            trade_count: k[8].as_u64().unwrap() as u32,
            taker_buy_volume: k[9].as_str().unwrap().parse().unwrap(),
            taker_buy_quote: k[10].as_str().unwrap().parse().unwrap(),
        })
        .collect();
    // 睡眠 1 秒
    sleep(Duration::from_secs(1)).await;
    Ok(candlesticks)
}

// 下单函数（修改为异步）
pub async fn place_order(
    symbol: String,
    order_side: Side,
    position: f64,
) -> Result<OrderResult, Box<dyn std::error::Error>> {
    let credentials = Credentials::from_hmac(
        get_load_global_config().binance_key.to_owned(),
        get_load_global_config().binance_secret.to_owned(),
    );
    // 创建一个带有自定义 URL 的 BinanceHttpClient
    let client =
        BinanceHttpClient::with_url(&*get_load_global_config().basic_url).credentials(credentials); // 示例：使用测试网 URL

    let quantity = Decimal::from_f64(position).ok_or(TradeError::DecimalError(
        "Failed to convert position to Decimal".to_string(),
    ))?;
    let request = trade::new_order(&symbol, order_side, "MARKET").quantity(quantity);

    let response = client
        .send(request)
        .await
        .map_err(|e| Box::new(TradeError::from(e)) as Box<dyn StdError>)?;
    let data = response
        .into_body_str()
        .await
        .map_err(|e| Box::new(TradeError::from(e)) as Box<dyn StdError>)?;
    let order: OrderResult = serde_json::from_str(&data)?;
    let order_id = order.order_id.to_string();
    println!(
        "成功执行 {} 下单 {} 数量 @ {} , 订单号：{}。",
        order_side, position, symbol, order_id
    );
    Ok(order)
}

// 平仓函数（修改为异步）
pub async fn close_position(
    symbol: String,
    order_side: Side,
    position: f64,
) -> Result<OrderResult, Box<dyn std::error::Error>> {
    let credentials = Credentials::from_hmac(
        get_load_global_config().binance_key.to_owned(),
        get_load_global_config().binance_secret.to_owned(),
    );
    // 创建一个带有自定义 URL 的 BinanceHttpClient
    let client =
        BinanceHttpClient::with_url(&*get_load_global_config().basic_url).credentials(credentials); // 示例：使用测试网 URL
    let quantity = Decimal::from_f64(position).ok_or(TradeError::DecimalError(
        "Failed to convert position to Decimal".to_string(),
    ))?;
    let request = trade::new_order(&symbol, order_side, "MARKET").quantity(quantity);
    let response = client
        .send(request)
        .await
        .map_err(|e| Box::new(TradeError::from(e)) as Box<dyn StdError>)?;
    let data = response
        .into_body_str()
        .await
        .map_err(|e| Box::new(TradeError::from(e)) as Box<dyn StdError>)?;
    let order: OrderResult = serde_json::from_str(&data)?;
    let order_id = order.order_id.to_string();
    println!(
        "成功执行 {} 平仓 {} 数量 @ {} , 订单号：{}。",
        order_side, position, symbol, order_id
    );
    Ok(order)
}

// 数据库保存函数（调整为单条记录）
fn save_to_db(
    symbol: String,
    entry_id: String,
    price: f64,
    order_type: String,
    order_side: String,
    position: f64,
    net_position: f64,
    order_id: String,
    order_status: String,
) -> Result<(), Box<dyn std::error::Error>> {
    let pool = Pool::new("mysql://steiner1976:12345678aA@@124.71.214.231:3306/ry_tiger")?;
    let mut conn = pool.get_conn()?;
    let create_time = Local::now().naive_local();
    let create_time_str = create_time.format("%Y-%m-%d %H:%M:%S").to_string();

    let data = SymbolOrderData::new(
        0,
        symbol,
        entry_id,
        price,
        order_type,
        order_side,
        position,
        net_position,
        order_id,
        order_status,
        create_time,
    );
    conn.exec_drop(
        r"INSERT INTO binance_vegas_records (symbol, entry_id, price, order_type, order_side, position, net_position, order_id,order_status, create_time)
          VALUES (:symbol, :entry_id, :price, :order_type, :order_side, :position, :net_position, :order_id,:order_status, :create_time)",
        params! {
            "symbol" => &data.symbol,
            "entry_id" => &data.entry_id,
            "price" => &data.price,
            "order_type" => &data.order_type,
            "order_side" => &data.order_side,
            "position" => &data.position,
            "net_position" => &data.net_position,
            "order_id" => &data.order_id,
            "order_status" => &data.order_status,
            "create_time" => &create_time_str,
        },
    )?;
    Ok(())
}

// 查询函数（保持不变）
fn query_from_db(
    entry_id: &str,
    symbol: &str,
) -> Result<Vec<SymbolOrderData>, Box<dyn std::error::Error>> {
    //localhost
    let pool = Pool::new("mysql://steiner1976:12345678aA@@124.71.214.231:3306/ry_tiger")?;
    let mut conn = pool.get_conn()?;
    let query = format!(
        "SELECT id, symbol, entry_id,price, order_type, order_side, position, net_position, order_id,order_status, create_time
     FROM binance_vegas_records
     WHERE entry_id = '{}' AND symbol = '{}' ORDER BY id DESC LIMIT 1",
        entry_id, symbol
    );

    let results = conn.query_map(
        query,
        |(
            id,
            symbol,
            entry_id,
            price,
            order_type,
            order_side,
            position,
            net_position,
            order_id,
            order_status,
            create_time,
        ): (
            i64,
            String,
            String,
            f64,
            String,
            String,
            f64,
            f64,
            String,
            String,
            String,
        )| {
            // Parse the datetime string back to NaiveDateTime
            let create_time_str = NaiveDateTime::parse_from_str(&create_time, "%Y-%m-%d %H:%M:%S")
                .unwrap_or_else(|_| NaiveDateTime::from_timestamp_opt(0, 0).unwrap());
            SymbolOrderData {
                id,
                symbol,
                entry_id,
                price,
                order_type,
                order_side,
                position,
                net_position,
                order_id,
                order_status,
                create_time: create_time_str,
            }
        },
    )?;
    Ok(results)
}
// 技术指标计算（保持不变）
fn ema(data: &[f64], period: usize) -> Vec<f64> {
    let mut result = Vec::with_capacity(data.len());
    let k = 2.0 / (period as f64 + 1.0);
    if data.is_empty() {
        return result;
    }
    result.push(data[0]);
    for i in 1..data.len() {
        let value = data[i] * k + result[i - 1] * (1.0 - k);
        result.push(value);
    }
    result
}

fn sma(data: &[f64], period: usize) -> Vec<f64> {
    let mut result = Vec::new();
    // 检查数据长度是否足够
    if data.len() < period {
        println!("Data length too short, returning empty result");
        return result;
    }
    // 计算可以生成多少个SMA值
    let num_sma = data.len() - period + 1;
    result.reserve(num_sma); // 预分配空间以提高性能

    // 使用更安全的循环范围
    for i in 0..num_sma {
        let start = i;
        let end = i + period - 1;
        // 确保索引在有效范围内
        if end < data.len() {
            let slice = &data[start..=end];
            let avg = slice.iter().sum::<f64>() / period as f64;
            result.push(avg);
        }
    }
    result
}

fn bollinger_bands(data: &[f64], period: usize, mult: f64) -> (Vec<f64>, Vec<f64>, Vec<f64>) {
    let basis = sma(data, period);
    let mut upper = Vec::new();
    let mut lower = Vec::new();

    // 如果basis为空，直接返回空结果
    if basis.is_empty() {
        return (Vec::new(), Vec::new(), Vec::new());
    }
    // 计算可以生成多少个布林带值
    let num_bands = basis.len();
    upper.reserve(num_bands);
    lower.reserve(num_bands);

    for i in 0..num_bands {
        let start = i;
        let end = i + period - 1;
        // 确保索引在有效范围内
        if end < data.len() {
            let slice = &data[start..=end];
            let mean = basis[i];
            let std_dev =
                (slice.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / period as f64).sqrt();
            upper.push(mean + mult * std_dev);
            lower.push(mean - mult * std_dev);
        }
    }
    (basis, upper, lower)
}

fn macd(data: &[f64], fast: usize, slow: usize) -> Vec<f64> {
    let fast_ema = ema(data, fast);
    let slow_ema = ema(data, slow);

    // 如果任一EMA为空，返回空结果
    if fast_ema.is_empty() || slow_ema.is_empty() {
        return Vec::new();
    }
    fast_ema
        .iter()
        .zip(slow_ema.iter())
        .map(|(f, s)| f - s)
        .collect()
}

// 修改后的交叉检测函数（去掉 i 参数）
// 因为触发时间为信号生成后，从币安获取的接口为当前K线数据，最新K线数据四个价格是变动的，因此计算从倒数的第二根K线和倒数第三根K线计算。
// crossover 以及crossunder 都是基于上面规则
fn crossover(a: &[f64], b: &[f64]) -> bool {
    let a_len = a.len();
    let b_len = b.len();
    if a_len < 3 || b_len < 3 {
        return false;
    }
    a[a_len - 3] <= b[b_len - 3] && a[a_len - 2] > b[b_len - 2]
}

fn crossunder(a: &[f64], b: &[f64]) -> bool {
    let a_len = a.len();
    let b_len = b.len();
    if a_len < 3 || b_len < 3 {
        return false;
    }
    a[a_len - 3] >= b[b_len - 3] && a[a_len - 2] < b[b_len - 2]
}

// close 下穿upper 需要
fn crossunder_upper(a: &[f64], b: &[f64]) -> bool {
    let a_len = a.len();
    let b_len = b.len();
    if a_len < 3 || b_len < 3 {
        return false;
    }
    a[a_len - 3] >= b[b_len - 3] * 0.999 && a[a_len - 2] < b[b_len - 2] * 0.999
}

// lower下穿 close
fn lower_crossunder(a: &[f64], b: &[f64]) -> bool {
    let a_len = a.len();
    let b_len = b.len();
    if a_len < 3 || b_len < 3 {
        return false;
    }
    a[a_len - 3] * 0.999 >= b[b_len - 3] && a[a_len - 2] * 0.999 < b[b_len - 2]
}

#[derive(Debug)]
enum TradeError {
    HyperError(Error),
    SerdeError(serde_json::Error),
    DecimalError(String),
}

impl fmt::Display for TradeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            TradeError::HyperError(e) => write!(f, "Hyper error: {:?}", e),
            TradeError::SerdeError(e) => write!(f, "Serde error: {}", e),
            TradeError::DecimalError(msg) => write!(f, "Decimal error: {}", msg),
        }
    }
}

impl StdError for TradeError {}

impl From<binance_spot_connector_rust::hyper::Error> for TradeError {
    fn from(err: binance_spot_connector_rust::hyper::Error) -> Self {
        TradeError::HyperError(err)
    }
}

impl From<serde_json::Error> for TradeError {
    fn from(err: serde_json::Error) -> Self {
        TradeError::SerdeError(err)
    }
}
